package br.trainee.web.dao.impl;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;
import javax.enterprise.context.RequestScoped;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.transaction.UserTransaction;

import br.trainee.web.vo.ClinicaTelefoneClinicaVO;
import br.trainee.web.vo.ClinicaVO;
import br.trainee.web.vo.EmailClinicaVO;
import br.trainee.web.vo.EnderecoClinicaVO;
import br.trainee.web.vo.StatusVO;
import br.trainee.web.vo.TelefoneClinicaVO;

@RequestScoped
public class TesteDAO implements Serializable{

	private static final long serialVersionUID = 1L;
	
	@Resource
	private UserTransaction t;
	
	@PersistenceContext(unitName="WebJsf")
	private EntityManager em;
	
	public List<ClinicaVO> buscarTodasClinicas() throws Exception{
		
		List<ClinicaVO> listaClinicas = null;
		
		t.begin();
		
			Query query = em.createNamedQuery("queryBuscarTodasClincas");
			
			listaClinicas = query.getResultList();
			
		t.commit();
		
		return listaClinicas;
	}
	
	public ClinicaVO buscarClinicaPorCnpj(String cnpj) throws Exception{
		
		ClinicaVO clinica = null;
		Object[] colunas = null;
		
		try{
		
		t.begin();
			
			//Só vai deixar com trim se no banco estiver como varchar, no caso de char não se usar trim, apenas para teste
			Query query = em.createNamedQuery("queryBuscarClinicaPorCnpj");
			
			query.setParameter("cnpj", cnpj);
			
			colunas = (Object[]) query.getSingleResult();
		
			clinica = new ClinicaVO();
			
			clinica.setIdPessoa((Long) colunas[0]);
			clinica.setNomePessoa((String) colunas[1]);
		
		t.commit();
		
		}
		catch(NoResultException e){
			
			clinica = null;
		}
		return clinica;
	}
	
	public List<ClinicaVO> buscarClinicasPorNome(String nome)throws Exception{
		
		t.begin();
			
			Query query = em.createNamedQuery("queryBuscarClinicaPorNome");
			
			query.setParameter("nome", "%"+nome.toLowerCase()+"%");
			
			List<ClinicaVO> listaClinicas = query.getResultList();
		
		t.commit();
		
		return listaClinicas;
	}
	
	public void alterarClinicaCompleto(ClinicaVO clinica) throws Exception{
		
		t.begin();
		
			em.merge(clinica);
		
		t.commit();
	}
	
	public boolean alterarClinica(ClinicaVO clinica) throws Exception{
		
		t.begin();
		
			Query query = em.createQuery("update ClinicaVO c set c.nomePessoa=:nomePessoa, c.cnpj=:cnpj where c.idPessoa=:idPessoa");
			query.setParameter("nomePessoa", clinica.getNomePessoa());
			query.setParameter("cnpj", clinica.getCnpj());
			query.setParameter("idPessoa", clinica.getIdPessoa());
			
			int linhas = query.executeUpdate();
		
		t.commit();
		
		return linhas > 0;
	}
	
	public void excluirClinica(Long id) throws Exception{
		
		t.begin();
			
			ClinicaVO clinica = em.find(ClinicaVO.class, id);
			
			em.remove(clinica);
		
		t.commit();
	}
	
	public ClinicaVO consultarClinicaPorId(Long idClinica) throws Exception{
		
		ClinicaVO clinica = null;
		
		t.begin();
		
		try{
			
			clinica = em.find(ClinicaVO.class, idClinica);
			
		}catch(NoResultException e){
			clinica = null;
		}
	
		t.commit();
		
		return clinica;
	}
	/**
	 * Nesse metodo busca tudo da clinica incluindo status
	 * @param idClinica
	 * @return
	 * @throws Exception
	 */
	public ClinicaVO consultarClinicaTudo(Long idClinica) throws Exception{
		
		ClinicaVO clinica = null;
		ClinicaVO clinicaRetorno = null;
		List<EmailClinicaVO> listaEmails = new ArrayList<EmailClinicaVO>();
		List<EnderecoClinicaVO> listaEnderecos = new ArrayList<EnderecoClinicaVO>();
		List<TelefoneClinicaVO> listaTelefones = new ArrayList<TelefoneClinicaVO>();

		
		
		try{
			
			t.begin();
			
			clinica = em.find(ClinicaVO.class, idClinica);
			
			clinicaRetorno = new ClinicaVO();
			//clinicaRetorno.setIdClinica(clinica.getIdClinica());
			//clinicaRetorno.setNomeClinica(clinica.getNomeClinica());
			//clinicaRetorno.setCnpj(clinica.getCnpj());
			//clinicaRetorno.setStatus(new StatusVO());
			//clinicaRetorno.getStatus().setIdStatus(clinica.getStatus().getIdStatus());
			//clinicaRetorno.getStatus().setTipoStatus(clinica.getStatus().getTipoStatus());
			//clinicaRetorno.getStatus().setDescricaoStatus(clinica.getStatus().getDescricaoStatus());
			
			
			for(EmailClinicaVO email: clinica.getEmails()){
				
				
				EmailClinicaVO emailEntrada = new EmailClinicaVO();
				
				emailEntrada = new EmailClinicaVO();
				emailEntrada.setIdEmailClinica(email.getIdEmailClinica());
				emailEntrada.setEmailClinica(email.getEmailClinica());
				emailEntrada.setStatus(new StatusVO());
				emailEntrada.getStatus().setIdStatus(email.getStatus().getIdStatus());
				emailEntrada.getStatus().setTipoStatus(email.getStatus().getTipoStatus());
				emailEntrada.getStatus().setDescricaoStatus(email.getStatus().getDescricaoStatus());
				emailEntrada.setClinica(email.getClinica());
				
				listaEmails.add(emailEntrada);
				
			}
			
			for(ClinicaTelefoneClinicaVO ct: clinica.getListaClinicaTelefone()){
				
				TelefoneClinicaVO telefoneEntrada = new TelefoneClinicaVO();
				
				telefoneEntrada.setIdTelefoneClinica(ct.getTelefone().getIdTelefoneClinica());
				telefoneEntrada.setDddClinica(ct.getTelefone().getDddClinica());
				telefoneEntrada.setTelefoneClinica(ct.getTelefone().getTelefoneClinica());
				telefoneEntrada.setTipoTelefone(ct.getTelefone().getTipoTelefone());
				telefoneEntrada.setStatus(new StatusVO());
				telefoneEntrada.getStatus().setIdStatus(ct.getTelefone().getStatus().getIdStatus());
				telefoneEntrada.getStatus().setTipoStatus(ct.getTelefone().getStatus().getTipoStatus());
				telefoneEntrada.getStatus().setDescricaoStatus(ct.getTelefone().getStatus().getDescricaoStatus());
			
				listaTelefones.add(telefoneEntrada);
			}
			
			for(EnderecoClinicaVO endereco: clinica.getEnderecos()){
				
				EnderecoClinicaVO enderecoEntrada = new EnderecoClinicaVO();
				
				enderecoEntrada.setIdEnderecoClinica(endereco.getIdEnderecoClinica());
				enderecoEntrada.setBairroClinica(endereco.getBairroClinica());
				enderecoEntrada.setCepClinica(endereco.getCepClinica());
				enderecoEntrada.setComplementoClinica(endereco.getComplementoClinica());
				enderecoEntrada.setLogradouroClinica(endereco.getLogradouroClinica());
				enderecoEntrada.setCidade(endereco.getCidade());
				enderecoEntrada.setStatus(new StatusVO());
				enderecoEntrada.getStatus().setIdStatus(endereco.getStatus().getIdStatus());
				enderecoEntrada.getStatus().setTipoStatus(endereco.getStatus().getTipoStatus());
				enderecoEntrada.getStatus().setDescricaoStatus(endereco.getStatus().getDescricaoStatus());
				enderecoEntrada.setClinica(endereco.getClinica());
				
				listaEnderecos.add(enderecoEntrada);
			}
			
			clinicaRetorno.setEmails(listaEmails);
			clinicaRetorno.setListaTelefones(listaTelefones);;
			clinicaRetorno.setEnderecos(listaEnderecos);
			
			t.commit();
		}catch(NoResultException e){
			clinica = null;
		}
	
		
		
		return clinicaRetorno;
	}
	
	public boolean excluirEmail(Long idEmail) throws Exception{
		
		t.begin();
		
			Query query = em.createQuery("delete from EmailClinicaVO e where e.idEmailClinica=:idEmailClinica");
			query.setParameter("idEmailClinica", idEmail);
			
			int linhas = query.executeUpdate();
		
		t.commit();
		
		return linhas > 0;
	}
	
	
	
	public TelefoneClinicaVO buscarTelefonePorNumeroEDdd(TelefoneClinicaVO telefone) throws Exception{
	
		TelefoneClinicaVO telefoneSaida = null;
		
		try{
		
		Query query = em.createNamedQuery("queryBuscarTelefonePorNumeroEDdd");
	
		query.setParameter("telefoneClinica", telefone.getTelefoneClinica());
		query.setParameter("dddClinica", telefone.getDddClinica());
		
		telefoneSaida = (TelefoneClinicaVO) query.getSingleResult();
		}
		catch(NoResultException e){
			
			telefoneSaida = null;
		}
		
		return telefoneSaida;
	}
	
	/**
	 * Nesse metodo não pode buscar o status, porque esta como lazy
	 * @param clinica
	 * @throws Exception
	 */
	public void incluirClinica(ClinicaVO clinica) throws Exception{
		
		t.begin();
		
			em.persist(clinica);
			
			for(ClinicaTelefoneClinicaVO ct: clinica.getListaClinicaTelefone()){
				
				ct.setClinica(clinica);
				
				TelefoneClinicaVO tel = buscarTelefonePorNumeroEDdd(ct.getTelefone());
				
				//Significa que o telefone não existe no banco, ou seja, deve ser cadastrado.
				if(tel == null){
					
					em.persist(ct.getTelefone());
				}
				else{
					
					ct.setTelefone(tel);
				}
				
				em.persist(ct);
			}
			
		t.commit();
		
		/*em.getTransaction().begin();
		
			em.persist(clinica);
			
			em.detach(clinica);
			
		em.getTransaction().commit();*/
	}
	
	public void incluirClinicaTelfone(ClinicaTelefoneClinicaVO ct) throws Exception{
		
		t.begin();
			ClinicaTelefoneClinicaVO ctEntrada = new ClinicaTelefoneClinicaVO();
		
			//ClinicaVO clinica = em.find(ClinicaVO.class, ct.getClinica().getIdClinica());
			TelefoneClinicaVO telefone = em.find(TelefoneClinicaVO.class, ct.getTelefone().getIdTelefoneClinica());
			
			//ctEntrada.setClinica(clinica);
			ctEntrada.setTelefone(telefone);
			ctEntrada.setOperadora(ct.getOperadora());
			
			em.persist(ctEntrada);
		
		t.commit();
	}
	
	public void alterarClinicaTelefone(ClinicaTelefoneClinicaVO ct)throws Exception{
		
		t.begin();
		
			ClinicaTelefoneClinicaVO ctEntrada = new ClinicaTelefoneClinicaVO();
			
			//ClinicaVO clinica = em.find(ClinicaVO.class, ct.getClinica().getIdClinica());
			TelefoneClinicaVO telefone = em.find(TelefoneClinicaVO.class, ct.getTelefone().getIdTelefoneClinica());
			
			//ctEntrada.setClinica(clinica);
			ctEntrada.setTelefone(telefone);
			
			ctEntrada.setOperadora(ct.getOperadora());
			
			em.merge(ctEntrada);
		
		t.commit();
	}
}
